package com.zareal.ymcc.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.zareal.ymcc.doc.CourseSearchDoc;
import com.zareal.ymcc.domain.*;
import com.zareal.ymcc.dto.CourseDto;
import com.zareal.ymcc.dto.MessageSmsDto;
import com.zareal.ymcc.dto.UserSmsDto;
import com.zareal.ymcc.enums.GlobalErrorCode;
import com.zareal.ymcc.feign.CourseSearchFeign;
import com.zareal.ymcc.feign.MediaFeignClient;
import com.zareal.ymcc.mapper.CourseMapper;
import com.zareal.ymcc.mapper.CourseTypeMapper;
import com.zareal.ymcc.result.JSONResult;
import com.zareal.ymcc.service.*;
import com.zareal.ymcc.util.AssertUtil;
import com.zareal.ymcc.vo.CourseDetailVo;
import com.zareal.ymcc.vo.CourseInfoVo;
import com.zareal.ymcc.vo.CourseOrderVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.zareal.ymcc.constans.MqConstants.COURSE_SMS_TAG;
import static com.zareal.ymcc.constans.MqConstants.COURSE_SMS_TOPIC;
/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Wilson
 * @since 2022-09-30
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {
    @Autowired
    private ITeacherService teacherServiceImpl;

    @Autowired
    private ICourseDetailService detailService;
    @Autowired
    private ICourseMarketService marketService;
    @Autowired
    private ICourseResourceService resourceService;
    @Autowired
    private CourseMapper courseMapper;
    @Autowired
    private ICourseSummaryService summaryService;

    @Autowired
    private CourseTypeMapper courseTypeMapper;

    @Autowired
    private CourseSearchFeign courseSearchFeign;
    @Autowired
    private MediaFeignClient mediaFeignClient;
    @Autowired
    private ICourseCollectService collectService;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private ICourseChapterService chapterService;
    @Override
    public void save(CourseDto courseDto) {
        // 1.JSR303校验参数
        // 2.提取参数
        Course course = courseDto.getCourse();
        CourseDetail courseDetail = courseDto.getCourseDetail();
        CourseMarket courseMarket = courseDto.getCourseMarket();
        CourseResource courseResource = courseDto.getCourseResource();
        List<Long> teacharIds = courseDto.getTeacharIds();

        // 3.检验后台是否存在相同名称的课程
        Course courseTmp = selectByName(course.getName());
        // 3.1断言课程是否存在
        AssertUtil.isNull(courseTmp, GlobalErrorCode.COURSE_IS_EXISTS);
        // 4 课程不存在，可以添加，查询老师的数据
        String teacherNames = teacherServiceImpl.selectBatchIds(teacharIds).stream().map(teacher -> teacher.getName())
                .collect(Collectors.joining(","));
        // 5 保存到数据库
        saveCourse(course, teacherNames);
        Long id = course.getId();
        // 6. 保存课程详情
        saveCourseDetail(courseDetail, id);
        // 7 保存课程销售
        saveCourseMarket(courseMarket, id);
        // 8 保存课程资源
        saveCourseResource(courseResource, id);
        // 9 添加老师和课程中间表
        courseMapper.saveTeacherByCourseId(id, teacharIds);
        // 10 保存课程类型总数量
        courseTypeMapper.updateTotalsById(course.getCourseTypeId());
        // 11 保存统计信息
        saveSummary(id);
    }

    @Override
    public void update(CourseDto courseDto) {
        // 1.JSR303校验参数
        // 2.提取参数
        Course course = courseDto.getCourse();
        CourseDetail courseDetail = courseDto.getCourseDetail();
        CourseMarket courseMarket = courseDto.getCourseMarket();
        CourseResource courseResource = courseDto.getCourseResource();
        List<Long> teacharIds = courseDto.getTeacharIds();
        Long id = course.getId();
        update(course);
        // 更新详情
        Wrapper<CourseDetail> detail = new EntityWrapper<>();
        detail.eq("id",id);
        detailService.update(courseDetail,detail);
        // 更新销售
        Wrapper<CourseMarket> market = new EntityWrapper<>();
        market.eq("id",id);
        marketService.update(courseMarket,market);

        // 更新资源
        Wrapper<CourseResource> resources = new EntityWrapper<>();
        resources.eq("id",id);
        resourceService.update(courseResource,resources);
        // 更新老师
        courseMapper.updateTeacherByCourseId(id, teacharIds);

    }

    private void update(Course course) {
        Wrapper<Course> wrapper = new EntityWrapper<>();
        wrapper.eq("id",course.getId());
        super.update(course, wrapper);
    }

    public CourseDto selectById(Long id) {
        CourseDto courseDto = new CourseDto();
        // 查询课程
        courseDto.setCourseDetail(detailService.selectById(id));
        // 查询销售
        courseDto.setCourseMarket(marketService.selectById(id));
        // 查询资源
        courseDto.setCourseResource(selectResourceByCourseId(id));
        // 查询老师和课程中间表
        courseDto.setTeacharIds(courseMapper.selectTeacherByCourseId(id));
        courseDto.setCourse(super.selectById(id));
        return courseDto;
    }
    // 课程上架
    @Override
    public void onLineCourse(Long courseId) {
        // 1.应该做断言，但是前端请求会拼接id，如果不存在，则访问不到
        // 2.根据id查询course对象
        Course course = super.selectById(courseId);
        // 断言课程存在，不存在抛异常
        AssertUtil.isNotNull(course,GlobalErrorCode.COURSE_IS_NULL);

        // 修改上架状态 先判定是否上架，断言
        AssertUtil.isFalse(course.getStatus().equals(Course.COURSE_ONLINE),GlobalErrorCode.COURSE_ALREADY_ONLINE);

        // 3.没上架则修改状态
        course.setStatus(Course.COURSE_ONLINE);
        updateById(course);

        // 调用ESopenfeign保存前台查询的时候需要的数据数据到es中
        // 4.1先找出需要保存的数据course
        //t_course_market
        //t_course_resource
        //t_course_summary
        //t_course_type
        CourseMarket courseMarket = marketService.selectById(courseId);
        Wrapper<CourseResource> wrapper = new EntityWrapper<>();
        wrapper.eq("course_id",courseId);
        CourseResource courseResource = resourceService.selectOne(wrapper);
        CourseSummary courseSummary = summaryService.selectById(courseId);
        CourseType courseType = courseTypeMapper.selectById(course.getCourseTypeId());

        CourseSearchDoc courseSearchDoc = new CourseSearchDoc();
        BeanUtils.copyProperties(course,courseSearchDoc);
        BeanUtils.copyProperties(courseMarket,courseSearchDoc);
        BeanUtils.copyProperties(courseResource,courseSearchDoc);
        BeanUtils.copyProperties(courseSummary,courseSearchDoc);
        // 没有courseTypeName字段
        courseSearchDoc.setCourseTypeName(courseType.getName());
        // 收费没有对应名字
        String chargeName = courseMarket.getCharge().equals(1) ? "收费" : "免费";
        courseSearchDoc.setChargeName(chargeName);

        // 5调用search微服务保存
        JSONResult jsonResult = courseSearchFeign.saveCourseEs(courseSearchDoc);
        // 判断是否成功
        AssertUtil.isTrue(jsonResult.isSuccess(),GlobalErrorCode.COURSE_SEARCH_FUSE);

        // 6
        senmessage(courseSearchDoc);

    }

    /**
     * 课程下架
     * @param courseId
     */
    @Override
    public void offLineCourse(Long courseId) {
        // 1.应该做断言，但是前端请求会拼接id，如果不存在，则访问不到
        // 2.根据id查询course对象
        Course course = super.selectById(courseId);
        // 断言课程存在，不存在抛异常
        AssertUtil.isNotNull(course,GlobalErrorCode.COURSE_IS_NULL);

        // 修改上架状态 先判定是否上架，断言
        AssertUtil.isFalse(course.getStatus().equals(Course.COURSE_offLINE),GlobalErrorCode.COURSE_ALREADY_OFFLINE);

        // 3.没上架则修改状态
        course.setStatus(Course.COURSE_offLINE);
        updateById(course);
        courseSearchFeign.deletCourseEs(courseId);
    }

    /**
     * 批量上架
     * @param ids
     */
    @Override
    public void patchOnLineCourse(List<Long> ids) {
        for (Long id : ids) {
            onLineCourse(id);
        }
    }

    @Override
    public void patchOffLineCourse(List<Long> ids) {
        for (Long id : ids) {
            offLineCourse(id);
        }
    }

    /**
     * 查询课程详情
     * @param courseId
     * @return
     */
    @Override
    public CourseDetailVo getDetail(Long courseId) {
        // 1.查询课程是否存在
        Course course = super.selectById(courseId);
        // 1.1课程是否存在
        AssertUtil.isNotNull(course,GlobalErrorCode.COURSE_IS_NULL);
        // 1.2根据课程判断是否上架
        AssertUtil.isTrue(course.getStatus()==Course.COURSE_ONLINE,GlobalErrorCode.COURSE_ALREADY_OFFLINE);
        // 2.1查询需要的内容，
//        private Course course;
//        private CourseMarket courseMarket;
//        private List<CourseChapter> courseChapters;
//        private List<Teacher> teachers;
//        private CourseDetail courseDetail;
//        private CourseSummary courseSummary;
        CourseMarket courseMarket = marketService.selectById(courseId);
        CourseDetail courseDetail = detailService.selectById(courseId);
        CourseSummary courseSummary = summaryService.selectById(courseId);
        List<Long> teacherIds = courseMapper.selectTeacherByCourseId(courseId);
        List<Teacher> teachers = teacherServiceImpl.selectBatchIds(teacherIds);
        Wrapper<CourseChapter> wrapper = new EntityWrapper<>();
        wrapper.eq("course_id", courseId);
        List<CourseChapter> courseChapters = chapterService.selectList(wrapper);
        // 根据章节数量，和id保存成map对象
        Map<Long, CourseChapter> courseChapterMap = courseChapters.stream().collect(Collectors.toMap(CourseChapter::getId, courseChapter -> courseChapter));
        JSONResult jsonResult = mediaFeignClient.selectMediaByCourseId(courseId);
        Object data = jsonResult.getData();
        AssertUtil.isNotNull(data,GlobalErrorCode.MEDIA_IS_NULL);
        List<MediaFile> mediaFiles = JSON.parseArray(data.toString(), MediaFile.class);
        mediaFiles.forEach(mediaFile -> {
            // 因为不清楚是否购买课程了没，所以不返回视频地址，点击视频的时候在获取 进行权限判断
            mediaFile.setFileUrl("");
            CourseChapter courseChapter = courseChapterMap.get(mediaFile.getChapterId());
            if (courseChapter != null) {
                courseChapter.getMediaFiles().add(mediaFile);
            }
        });
        return new CourseDetailVo(course, courseMarket, courseChapters, teachers, courseDetail, courseSummary);
    }

    @Override
    public CourseInfoVo getInfo(String courseIds) {
        // 1.判断ids是不是对的数组类型，且只能为数字
        String[] split = courseIds.split(",");
        Set<Long> collect = Arrays.stream(split)
                .filter(id -> id.matches("[A-Za-z0-9]"))
                .filter(id -> !StringUtils.isEmpty(id))
                .map(id -> Long.valueOf(id))
                .collect(Collectors.toSet());

        // 2. 防止传过来字符串1,dsa,3, ,,,,,类似于这种 判断长度是不是一样
        AssertUtil.isTrue(split.length == collect.size(),GlobalErrorCode.ORDER_COURSE_LENGTH_NOT_MATCH);

        // 3 查询所有课程
        List<Long> courseIdsList = collect.stream().collect(Collectors.toList());
        List<Course> courses = super.selectBatchIds(courseIdsList);
        // 断言是否为空
        AssertUtil.isNotNull(courses,GlobalErrorCode.COURSE_IS_NULL);

        // 3.1查询课程市场信息
        List<CourseMarket> courseMarkets = marketService.selectBatchIds(courseIdsList);
        Map<Long, CourseMarket> courseMarketMap = courseMarkets.stream().collect(Collectors.toMap(CourseMarket::getId, courseMarket -> courseMarket));
        // 总的信息
        CourseInfoVo courseInfoVo = new CourseInfoVo();
        // 数组装几种课程信息
        ArrayList<CourseOrderVo> courseOrderVos = new ArrayList<>();

        // 3.2把course循环放到courseordervos中
        courses.forEach(course -> {
            CourseOrderVo courseOrderVo = new CourseOrderVo();
            courseOrderVo.setCourse(course);
            CourseMarket courseMarket = courseMarketMap.get(course.getId());
            courseOrderVo.setCourseMarket(courseMarket);
            courseInfoVo.setTotalAmount(courseInfoVo.getTotalAmount().add(BigDecimal.valueOf(courseMarket.getPrice())));
            courseOrderVos.add(courseOrderVo);
        });
        courseInfoVo.setCourseInfos(courseOrderVos);
        return courseInfoVo;
    }

    // 根据收藏该课程的用户发送短信通知课程上架
    private void senmessage(CourseSearchDoc courseSearchDoc) {
        MessageSmsDto messageSmsDto = new MessageSmsDto();
        messageSmsDto.setTitle("课程发布");
        messageSmsDto.setContent("亲爱的用户您好，最新课程 <a href='localhost:6002/list.html?courseId="+courseSearchDoc.getId()+"'> 测试 </a> 发布啦，点击课程了解详情");
        // 获取需要发送短信的用户
        Wrapper<CourseCollect> wrapper = new EntityWrapper<>();
        wrapper.eq("course_id",courseSearchDoc.getId());
        // 获取用户收藏信息
        List<CourseCollect> collectList = collectService.selectList(wrapper);
        List<UserSmsDto> userSmsDtoList = new ArrayList<>();
        for (CourseCollect courseCollect : collectList) {
            userSmsDtoList.add(new UserSmsDto(courseCollect.getUserId(), courseCollect.getPhone()));
        };
        messageSmsDto.setUsers(userSmsDtoList);
        rocketMQTemplate.sendOneWay(COURSE_SMS_TOPIC + ":" +COURSE_SMS_TAG, JSON.toJSONString(messageSmsDto));

    }

    private CourseResource selectResourceByCourseId(Serializable id) {
        Wrapper<CourseResource> wrapper = new EntityWrapper<>();
        wrapper.eq("course_id", id);
        return resourceService.selectOne(wrapper);
    }

    @Override
    public boolean deleteById(Serializable id) {
        // 删除课程
        detailService.deleteById(id);
        // 删除销售
        marketService.deleteById(id);
        // 删除资源
        deleteResourceByCourseId(id);
        // 删除老师和课程中间表
        courseMapper.deletTeacherByCourseId(id);
        // 课程总数量减一
        Course course = selectById(id);
        courseTypeMapper.reduceTotalsById(course.getCourseTypeId());
        // 统计信息
        summaryService.deleteById(id);
        return super.deleteById(id);
    }

    private void deleteResourceByCourseId(Serializable id) {
        Wrapper<CourseResource> wrapper = new EntityWrapper<>();
        wrapper.eq("course_id", id);
        resourceService.delete(wrapper);
    }

    private void saveSummary(Long id) {
        CourseSummary courseSummary = new CourseSummary();
        courseSummary.setId(id);
        summaryService.insert(courseSummary);
    }

    private void saveCourseResource(CourseResource courseResource, Long id) {
        courseResource.setCourseId(id);
        resourceService.insert(courseResource);
    }

    private void saveCourseMarket(CourseMarket courseMarket, Long id) {
        courseMarket.setId(id);
        marketService.insert(courseMarket);
    }

    private void saveCourseDetail(CourseDetail courseDetail, Long id) {
        courseDetail.setId(id);
        detailService.insert(courseDetail);
    }

    private void saveCourse(Course course, String teacherNames) {
        course.setStatus(Course.COURSE_ONLINE);
        course.setTeacherNames(teacherNames);
        course.setLoginId(3L);
        course.setLoginUserName("13330964748");
        insert(course);
    }

    // 查询数据库中存在同名的课程
    private Course selectByName(String name) {
        Wrapper<Course> wrapper = new EntityWrapper<>();
        wrapper.eq("name", name);
        return selectOne(wrapper);
    }
}
